/*
 * main.cc
 *
 *   Created on: 2010-3-31     
 *  Description: Benchmark on json-rpc-e
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#include <pthread.h>
#include <stdio.h>
#include <stdexcept>
#include <cstdlib>
#include <string>
#include <sys/time.h>
using std::runtime_error;

#include "function.h"

#include <json-rpc-e/util/Util.h>
#include <json-rpc-e/net/EasyAddr.h>

//持续多少秒?
unsigned int t = 0;
//失败的次数
unsigned long nFail = 0;
//成功的次数
unsigned long nSuccess = 0;

//是否继续运行
bool run = true;

//需要的总线程数量
unsigned long concurrent = 0;
//需要的总线程数量
unsigned long cAlive = 0;

//ip
std::string ip;
//port
unsigned int port;

//额外的fd
unsigned long extraFd;

//(n监视)
pthread_spinlock_t spin_n;

//同步start
pthread_mutex_t mutex_start;
//同步start
pthread_cond_t cond_start;

struct timeval tv1, tv2;
void start()
{
	gettimeofday(&tv1, NULL);
}

void end()
{
	gettimeofday(&tv2, NULL);
	unsigned long timeuse = 1000000 * (tv2.tv_sec - tv1.tv_sec) + tv2.tv_usec
			- tv1.tv_usec;
	timeuse /= 1000;
	printf("Cost %lu ms.\n", timeuse);
}

void* thread_func(void *arg)
{
	//	unsigned int me = *(unsigned int *) arg;
	//等待开始
	pthread_mutex_lock(&mutex_start);
	pthread_cond_wait(&cond_start, &mutex_start);
	pthread_mutex_unlock(&mutex_start);

	while (run)
	{
		//调用方法
		/*		printf("Hint in %u\n", me);*/

		if (test_a_add_b(ip, port))
		{
			//成功记录
			pthread_spin_lock(&spin_n);
			nSuccess++;
			pthread_spin_unlock(&spin_n);
		}
		else
		{
			//失败需要记录
			pthread_spin_lock(&spin_n);
			nFail++;
			pthread_spin_unlock(&spin_n);
		}
	}

	return NULL;
}

//初始化线程
void init()
{
	//设置Detached
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
	{
		throw runtime_error("set detached in pthread_attr fail.");
	}
	//创建线程
	cAlive = concurrent;
	for (unsigned int i = 0; i < concurrent; i++)
	{
		pthread_t tid;
		if (pthread_create(&tid, &attr, thread_func, (void *) &i))
		{
			throw runtime_error("create thread fail.");
		}
	}

	pthread_attr_destroy(&attr);
	printf("wake up all thread\n");
	//唤醒所有wait_cond
	pthread_mutex_lock(&mutex_start);
	start();
	pthread_cond_broadcast(&cond_start);
	pthread_mutex_unlock(&mutex_start);

	//等待t秒
	sleep(t);
	run = false;
	end();

}

void openExtraFd()
{
	//创建extraFd个空闲连接，但是不关闭
	EasyAddr addr;
	addr.ip = ip;
	addr.port = port;
	for (unsigned long i = 0; i < extraFd; i++)
	{
		int sock = Network::socket();
		if (!Network::connect(sock, addr))
		{
			printf("extra connect fail.\n");
		}
	}
}

//调用参数 t c ip port extraFd前者是总request数量，后者是并发线程数量
int main(int argc, char **argv)
{
	if (argc != 6)
	{
		printf("Usage benchmark [time] [concurrency] [ip] [port] [extra fd]\n");
		return -1;
	}
	else
	{
		t = atol(argv[1]);
		concurrent = atoi(argv[2]);
		ip = std::string(argv[3]);
		port = atoi(argv[4]);
		extraFd = atol(argv[5]);

		printf("Testing %s:%u Total %u(s) in %lu threads\n", ip.c_str(), port,
				t, concurrent);
	}

	//初始化
	pthread_spin_init(&spin_n, 0);
	pthread_mutex_init(&mutex_start, 0);
	pthread_cond_init(&cond_start, 0);

	Util::setFDLimit();//fd 最多102400
	openExtraFd(); //打开额外的fd
	init();

	printf("Finish : %lu success, %lu fails.\n", nSuccess, nFail);

	//销毁
	pthread_spin_destroy(&spin_n);
	pthread_mutex_destroy(&mutex_start);
	pthread_cond_destroy(&cond_start);
}

